home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include "proto.h"
- #include "parwave.h"
- #include "hplay.h"
- #include "dict.h"
- #include "ASCII.h"
- #include "darray.h"
- #include "holmes.h"
- #include "phtoelm.h"
- #include "text.h"
- #include "say.h"
-
- int synthesis_model = ALL_PARALLEL;
- long nfcascade = 4;
- long nspfr;
- long sigmx;
- long warnsw, dispt, disptcum;
- int bDebug = 0;
- FILE *debug1, *debug2;
-
- dict_t *dict;
-
- unsigned
- spell_out(word, n, phone)
- char *word;
- int n;
- darray_ptr phone;
- {
- unsigned nph = 0;
- fprintf(stderr, "Spelling '%.*s'\n", n, word);
- while (n-- > 0)
- {
- nph += xlate_string(ASCII[toascii(*word++)], phone);
- }
- return nph;
- }
-
- int
- suspect_word(s, n)
- char *s;
- int n;
- {
- int i = 0;
- int seen_lower = 0;
- int seen_upper = 0;
- int seen_vowel = 0;
- int last = 0;
- for (i = 0; i < n; i++)
- {
- char ch = *s++;
- if (i && last != '-' && isupper(ch))
- seen_upper = 1;
- if (islower(ch))
- {
- seen_lower = 1;
- ch = toupper(ch);
- }
- if (ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' || ch == 'Y')
- seen_vowel = 1;
- last = ch;
- }
- return !seen_vowel || (seen_upper && seen_lower) || !seen_lower;
- }
-
- static unsigned xlate_word PROTO((char *word, int n, darray_ptr phone));
-
-
- static unsigned
- xlate_word(word, n, phone)
- char *word;
- int n;
- darray_ptr phone;
- {
- unsigned nph = 0;
- if (*word != '[')
- {
- if (dict)
- {
- dictrec_ptr p = spell_find(dict, word, n);
- if (p)
- {
- char *s = p->pronounce;
- char *e = p->pronounce + sizeof(p->pronounce);
- #if 0
- fprintf(stderr, "Dict '%.*s'\n", n, word);
- #endif
- /* may need to modify dictionary's idea of phonemes here,
- as (for example) final :-> /'faInl/ does not work as it stands.
- This is probably part of a deeper problem concerning
- which allophone to use for a particular phoneme in context.
- */
- while (e > s && isspace(e[-1]))
- e--;
- while (s < e)
- phone_append(phone, *s++);
- phone_append(phone, ' ');
- return nph + 1;
- }
- else
- {
- /* If supposed word contains '.' or '-' try breaking it up...*/
- char *h = word;
- while (h < word + n)
- {
- if (*h == '.' || *h == '-')
- {
- nph += xlate_word(word, h++ - word, phone);
- nph += xlate_word(h, word + n - h, phone);
- return nph;
- }
- else
- h++;
- }
- }
- }
- if (suspect_word(word, n))
- return spell_out(word, n, phone);
- else
- {
- fprintf(stderr, "Guess '%.*s'\n", n, word);
- nph += NRL(word, n, phone);
- }
- }
- else
- {
- if ((++word)[(--n) - 1] == ']')
- n--;
- while (n-- > 0)
- {
- phone_append(phone,*word++);
- nph++;
- }
- }
- phone_append(phone, ' ');
- return nph + 1;
- }
-
-
- void
- say_phones(phone, len)
- char *phone;
- int len;
- {
- darray_t elm;
- unsigned frames;
- darray_init(&elm, sizeof(char), len);
- if ((frames = phone_to_elm(phone, len, &elm)))
- {
- unsigned max_samples = frames * nspfr;
- short *samp = (short *) malloc(sizeof(short) * max_samples);
- printf("%.*s\n", len, phone);
- if (samp)
- {
- unsigned nsamp = holmes(elm.items, (unsigned char *) darray_find(&elm, 0),
- max_samples, samp);
- audio_play(nsamp, samp);
- free(samp);
- }
- }
- darray_free(&elm);
- }
-
- unsigned
- xlate_string(string, phone)
- char *string;
- darray_ptr phone;
- {
- unsigned nph = 0;
- char *s = string;
- char ch;
- while (isspace(ch = *s))
- s++;
- while ((ch = *s))
- {
- char *word = s;
- if (isalpha(ch))
- {
- while (isalpha(ch = *s) || ((ch == '\'' || ch == '-' || ch == '.') && isalpha(s[1])))
- s++;
- if (!ch || isspace(ch) || ispunct(ch) || (isdigit(ch) && !suspect_word(word, s - word)))
- nph += xlate_word(word, s - word, phone);
- else
- {
- while ((ch = *s) && !isspace(ch) && !ispunct(ch))
- s++;
- nph += spell_out(word, s - word, phone);
- }
- }
- else if (isdigit(ch) || (ch == '-' && isdigit(s[1])))
- {
- int sign = (ch == '-') ? -1 : 1;
- long value = 0;
- if (sign < 0)
- ch = *++s;
- while (isdigit(ch = *s))
- {
- value = value * 10 + ch - '0';
- s++;
- }
- if (ch == '.' && isdigit(s[1]))
- {
- word = ++s;
- nph += xlate_cardinal(value * sign, phone);
- nph += xlate_string("point", phone);
- while (isdigit(ch = *s))
- s++;
- nph += spell_out(word, s - word, phone);
- }
- else
- {
- /* check for ordinals, date, time etc. can go in here */
- nph += xlate_cardinal(value * sign, phone);
- }
- }
- else if (ch == '[' && strchr(s,']'))
- {char *word = s;
- while (*s && *s++ != ']')
- /* nothing */;
- nph += xlate_word(word, s - word, phone);
- }
- else if (ispunct(ch))
- {
- switch (ch)
- {
- /* On end of sentence flush the buffer ... */
- case '!':
- case '?':
- case '.':
- if ((!s[1] || isspace(s[1])) && phone->items)
- {
- say_phones((char *) darray_find(phone, 0), phone->items);
- phone->items = 0;
- }
- s++;
- phone_append(phone, ' ');
- break;
- case '"': /* change pitch ? */
- case ':':
- case '-':
- case ';':
- case ',':
- case '(':
- case ')':
- s++;
- phone_append(phone, ' ');
- break;
- case '[':
- {char *e = strchr(s,']');
- if (e)
- {
- s++;
- while (s < e)
- phone_append(phone,*s++);
- s = e+1;
- break;
- }
- }
- default:
- nph += spell_out(word, 1, phone);
- s++;
- break;
- }
- }
- else
- {
- while ((ch = *s) && !isspace(ch))
- s++;
- nph += spell_out(word, s - word, phone);
- }
- while (isspace(ch = *s))
- s++;
- }
- return nph;
- }
-
- char *
- concat_args(argc, argv)
- int argc;
- char *argv[];
- {
- int len = 0;
- int i;
- char *buf;
- for (i = 1; i < argc; i++)
- len += strlen(argv[i]) + 1;
- buf = (char *) malloc(len);
- if (buf)
- {
- char *d = buf;
- for (i = 1; i < argc;)
- {
- char *s = argv[i++];
- while (*s)
- *d++ = *s++;
- if (i < argc)
- *d++ = ' ';
- else
- *d = '\0';
- }
- }
- return buf;
- }
-
- void
- say_string(s)
- char *s;
- {
- darray_t phone;
- darray_init(&phone, sizeof(char), 128);
- xlate_string(s, &phone);
- if (phone.items)
- say_phones((char *) darray_find(&phone, 0), phone.items);
- darray_free(&phone);
- }
-
- extern int darray_fget PROTO((FILE *f, darray_ptr p));
-
- int
- darray_fget(f, p)
- FILE *f;
- darray_ptr p;
- {
- int ch;
- while ((ch = fgetc(f)) != EOF)
- {
- phone_append(p, ch);
- if (ch == '\n')
- break;
- }
- phone_append(p, '\0');
- return p->items - 1;
- }
-
- extern void say_file PROTO((FILE *f));
-
- void
- say_file(f)
- FILE *f;
- {
- darray_t line;
- darray_t phone;
- darray_init(&line, sizeof(char), 128);
- darray_init(&phone, sizeof(char), 128);
- while (darray_fget(f, &line))
- {
- xlate_string((char *) darray_find(&line, 0), &phone);
- line.items = 0;
- }
- if (phone.items)
- say_phones((char *) darray_find(&phone, 0), phone.items);
- darray_free(&phone);
- darray_free(&line);
- }
-
- int main PROTO((int argc, char *argv[], char *env[]));
-
- int
- main(argc, argv, env)
- int argc;
- char *argv[];
- char *env[];
- {
- dict_t d;
- argc = audio_init(argc, argv);
- argc = init_synth(argc, argv);
- argc = init_holmes(argc, argv);
- if (dict_init(&d, NULL))
- dict = &d;
- if (argc > 1)
- {
- char *s = concat_args(argc, argv);
- if (s)
- {
- say_string(s);
- free(s);
- }
- }
- else
- say_file(stdin);
- audio_term();
- term_holmes();
- if (dict)
- dict_term(dict);
- return (0);
- }
-